package com.yijiu.algorithm;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import android.util.Base64;

/**
 * RSA安全编码组件
 * 
 * @author network
 * @version 1.0
 * @since 1.0
 */
public abstract class RSACoder extends Coder {

	public static final String KEY_ALGORITHM = "RSA";

	public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

	/** 默认的安全服务提供者 */
	// private static final Provider DEFAULT_PROVIDER = new
	// BouncyCastleProvider();

	private static final String PUBLIC_KEY = "RSAPublicKey";

	private static final String PRIVATE_KEY = "RSAPrivateKey";

	private static final String RSA_PUBKEY_FILENAME = "/__YIJIU_RSA_PUBKEY.txt";

	private static final String RSA_PRIKEY_FILENAME = "/__YIJIU_RSA_PRIKEY.txt";

	/** 缓存的密钥对。 */
	// private static KeyPair oneKeyPair = null;
	/** 缓存的密钥对。 */
	private static RSAPublicKey yijiuPublicKey = null;

	private static RSAPrivateKey yijiuPrivateKey = null;

	private static File yijiuPublicKeyFile = null;

	private static File yijiuPrivateKeyFile = null;

	static final int KEY_SIZE = 1024;

	private static final String RSA_PUBLICE = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPZ1Ju6zzYUoL7HYzLgneROyDC" + "\r" + "Qf/NANWGO42FfXwQinYVSpqnmtukGLsOhVuwdNH6aRFE0ms3bkpp/WL4cfVDgnCO" + "\r" + "+W9J6vRVpuTuD/iqfJd9TNacLCd3Jvg3HhjqxbJeO74fYnYqo/mmyJSeLE5iZg4I" + "\r" + "Zm5LPWBZWUp3ULCAZQIDAQAB";

	private static final String ALGORITHM = "RSA";

	// /**
	// * 用私钥对信息生成数字签名
	// *
	// * @param data
	// * 加密数据
	// * @param privateKey
	// * 私钥
	// * @return
	// * @throws Exception
	// */
	// public static String sign(byte[] data, String privateKey) throws
	// Exception {
	// // 解密由base64编码的私钥
	// byte[] keyBytes = decryptBASE64(privateKey);
	//
	// // 构造PKCS8EncodedKeySpec对象
	// PKCS8EncodedKeySpec pkcs8KeySpec = new
	// PKCS8EncodedKeySpec(keyBytes);
	//
	// // KEY_ALGORITHM 指定的加密算法
	// KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
	//
	// // 取私钥匙对象
	// PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
	//
	// // 用私钥对信息生成数字签名
	// Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
	// signature.initSign(priKey);
	// signature.update(data);
	//
	// return encryptBASE64(signature.sign());
	// }
	//
	// /**
	// * 校验数字签名
	// *
	// * @param data
	// * 加密数据
	// * @param publicKey
	// * 公钥
	// * @param sign
	// * 数字签名
	// * @return 校验成功返回true 失败返回false
	// * @throws Exception
	// */
	// public static boolean verify(byte[] data, String publicKey, String
	// sign) throws Exception {
	//
	// // 解密由base64编码的公钥
	// byte[] keyBytes = decryptBASE64(publicKey);
	//
	// // 构造X509EncodedKeySpec对象
	// X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
	//
	// // KEY_ALGORITHM 指定的加密算法
	// KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
	//
	// // 取公钥匙对象
	// PublicKey pubKey = keyFactory.generatePublic(keySpec);
	//
	// Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
	// signature.initVerify(pubKey);
	// signature.update(data);
	//
	// // 验证签名是否正常
	// return signature.verify(decryptBASE64(sign));
	// }
	//
	// /**
	// * 解密<br>
	// * 用私钥解密
	// *
	// * @param data
	// * @param key
	// * @return
	// * @throws Exception
	// */
	// public static byte[] decryptByPrivateKey(byte[] data, String key)
	// throws Exception {
	// // 对密钥解密
	// byte[] keyBytes = decryptBASE64(key);
	//
	// // 取得私钥
	// PKCS8EncodedKeySpec pkcs8KeySpec = new
	// PKCS8EncodedKeySpec(keyBytes);
	// KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
	// Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
	//
	// // 对数据解密
	// Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
	// cipher.init(Cipher.DECRYPT_MODE, privateKey);
	//
	// return cipher.doFinal(data);
	// }
	//
	// /**
	// * 解密<br>
	// * 用公钥解密
	// *
	// * @param data
	// * @param key
	// * @return
	// * @throws Exception
	// */
	// public static byte[] decryptByPublicKey(byte[] data, String key)
	// throws Exception {
	// // 对密钥解密
	// byte[] keyBytes = decryptBASE64(key);
	//
	// // 取得公钥
	// X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
	// KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
	// Key publicKey = keyFactory.generatePublic(x509KeySpec);
	//
	// // 对数据解密
	// Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
	// cipher.init(Cipher.DECRYPT_MODE, publicKey);
	//
	// return cipher.doFinal(data);
	// }
	//
	// /**
	// * 加密<br>
	// * 用公钥加密
	// *
	// * @param data
	// * @param key
	// * @return
	// * @throws Exception
	// */
	// public static byte[] encryptByPublicKey(byte[] data, String key)
	// throws Exception {
	// // 对公钥解密
	// byte[] keyBytes = decryptBASE64(key);
	//
	// // 取得公钥
	// X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
	// KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
	// Key publicKey = keyFactory.generatePublic(x509KeySpec);
	//
	// // 对数据加密
	// // Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
	// Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
	// cipher.init(Cipher.ENCRYPT_MODE, publicKey);
	//
	//
	//
	// return cipher.doFinal(data);
	// }
	//
	// /**
	// * 加密<br>
	// * 用私钥加密
	// *
	// * @param data
	// * @param key
	// * @return
	// * @throws Exception
	// */
	// public static byte[] encryptByPrivateKey(byte[] data, String key)
	// throws Exception {
	// // 对密钥解密
	// byte[] keyBytes = decryptBASE64(key);
	//
	// // 取得私钥
	// PKCS8EncodedKeySpec pkcs8KeySpec = new
	// PKCS8EncodedKeySpec(keyBytes);
	// KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
	// Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
	//
	// // 对数据加密
	// Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
	// cipher.init(Cipher.ENCRYPT_MODE, privateKey);
	//
	// return cipher.doFinal(data);
	// }
	//
	// /**
	// * 取得私钥
	// *
	// * @param keyMap
	// * @return
	// * @throws Exception
	// */
	// public static String getPrivateKey(Map<String, Object> keyMap)
	// throws Exception {
	// Key key = (Key) keyMap.get(PRIVATE_KEY);
	//
	// return encryptBASE64(key.getEncoded());
	// }
	//
	// /**
	// * 取得公钥
	// *
	// * @param keyMap
	// * @return
	// * @throws Exception
	// */
	// public static String getPublicKey(Map<String, Object> keyMap)
	// throws Exception {
	// Key key = (Key) keyMap.get(PUBLIC_KEY);
	//
	// return encryptBASE64(key.getEncoded());
	// }

	/**
	 * 初始化密钥
	 * 
	 * @return
	 * @throws Exception
	 */
	// public static Map<String, Object> initKey() throws Exception {
	// KeyPairGenerator keyPairGen =
	// KeyPairGenerator.getInstance(KEY_ALGORITHM, new
	// org.bouncycastle.jce.provider.BouncyCastleProvider());
	// keyPairGen.initialize(KEY_SIZE, new
	// SecureRandom(DateFormatUtils.format(new Date(),
	// "yyyyMMdd").getBytes()));
	//
	// KeyPair keyPair = keyPairGen.generateKeyPair();
	// // 公钥
	// RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
	//
	// // 私钥
	// RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
	//
	// Map<String, Object> keyMap = new HashMap<String, Object>(2);
	//
	// keyMap.put(PUBLIC_KEY, publicKey);
	// keyMap.put(PRIVATE_KEY, privateKey);
	// return keyMap;
	// }

	/**
	 * 若需要创建新的密钥对文件，则返回 {@code true}，否则 {@code false}。
	 */
	private static boolean isCreateKeyPairFile(String type) {
		// 是否创建新的密钥对文件
		boolean createNewKeyPair = false;
		if ("public".equals(type)) {
			if (!yijiuPublicKeyFile.exists() || yijiuPublicKeyFile.isDirectory()) {
				createNewKeyPair = true;
			}
		} else {
			if (!yijiuPrivateKeyFile.exists() || yijiuPrivateKeyFile.isDirectory()) {
				createNewKeyPair = true;
			}
		}
		return createNewKeyPair;
	}

	/**
	 * 得到公钥
	 * 
	 * @param algorithm
	 * @param bysKey
	 * @return
	 */
	private static PublicKey getPublicKeyFromX509(String algorithm, String bysKey) throws NoSuchAlgorithmException, Exception {
		byte[] decodedKey = Base64.decode(bysKey, Base64.DEFAULT);
		X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodedKey);

		KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
		return keyFactory.generatePublic(x509);
	}

	/**
	 * 使用公钥加密
	 * 
	 * @param content
	 * @param key
	 * @return
	 */
	public static String encryptByPublic(String content, String key) {
		try {
			PublicKey pubkey = getPublicKeyFromX509(ALGORITHM, key);

			Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			cipher.init(Cipher.ENCRYPT_MODE, pubkey);

			byte plaintext[] = content.getBytes("UTF-8");
			byte[] output = cipher.doFinal(plaintext);

			String s = new String(Base64.encode(output, Base64.DEFAULT));

			return s;

		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 使用公钥解密
	 * 
	 * @param content
	 *            密文
	 * @param key
	 *            商户私钥
	 * @return 解密后的字符串
	 */
	public static String decryptByPublic(String content) {
		try {
			PublicKey pubkey = getPublicKeyFromX509(ALGORITHM, RSA_PUBLICE);
			Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			cipher.init(Cipher.DECRYPT_MODE, pubkey);
			InputStream ins = new ByteArrayInputStream(Base64.decode(content, Base64.DEFAULT));
			ByteArrayOutputStream writer = new ByteArrayOutputStream();
			byte[] buf = new byte[128];
			int bufl;
			while ((bufl = ins.read(buf)) != -1) {
				byte[] block = null;
				if (buf.length == bufl) {
					block = buf;
				} else {
					block = new byte[bufl];
					for (int i = 0; i < bufl; i++) {
						block[i] = buf[i];
					}
				}
				writer.write(cipher.doFinal(block));
			}
			return new String(writer.toByteArray(), "utf-8");
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 初始化密钥Map
	 * 
	 * @return
	 * @throws Exception
	 */
	// public static Map<String, Object> generateKeyMap() throws Exception
	// {
	// KeyPairGenerator keyPairGen =
	// KeyPairGenerator.getInstance(KEY_ALGORITHM, DEFAULT_PROVIDER);
	// keyPairGen.initialize(KEY_SIZE, new
	// SecureRandom(DateFormatUtils.format(new Date(),
	// "yyyyMMdd").getBytes()));
	//
	// KeyPair keyPair = keyPairGen.generateKeyPair();
	// // 公钥
	// RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
	//
	// // 私钥
	// RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
	// Map<String, Object> keyPairMap = new HashMap<String, Object>(2);
	// keyPairMap.put(PUBLIC_KEY, encryptBASE64(publicKey.getEncoded()));
	// keyPairMap.put(PRIVATE_KEY,
	// encryptBASE64(privateKey.getEncoded()));
	// return keyPairMap;
	// }
}
